
#include "pika_hal_ex.h"

#ifdef PIKA_HAL_SIMPLE_DEQUE
pika_hal_deque* pika_hal_deque_create(size_t capacity) {
    pika_hal_deque* cb = (pika_hal_deque*)pikaMalloc(sizeof(pika_hal_deque));
    if (NULL == cb) {
        return NULL;
    }
    cb->head = 0;
    cb->tail = 0;
    cb->count = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_init(&cb->mutex);
#endif
    cb->capacity = capacity;
    cb->buffer = (void**)pikaMalloc(capacity * sizeof(void*));  // 分配足够的空间来存储指针
    if (NULL == cb->buffer) {
        pikaFree(cb, sizeof(pika_hal_deque));
        return NULL;
    }
    return cb;
}

int pika_hal_deque_appendTail(pika_hal_deque* cb, void* value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    if (cb->count == cb->capacity) {
        ret = -1;
        goto __exit;
    }

    cb->buffer[cb->tail] = value;
    cb->tail = (cb->tail + 1) % cb->capacity;
    cb->count++;
__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&cb->mutex);
#endif
    return ret;
}

//以下待测试
int pika_hal_deque_appendHead(pika_hal_deque* cb, void* value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    if (cb->count == cb->capacity) {
        ret = -1;  // 队列已满
        goto __exit;
    }

    // 更新 head 指针前的位置，然后更新 head
    cb->head = (cb->head - 1 + cb->capacity) % cb->capacity;
    cb->buffer[cb->head] = value;
    cb->count++;
__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&cb->mutex);
#endif
    return ret;
}

int pika_hal_deque_popHead(pika_hal_deque* cb, void** value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    if (cb->count == 0) {
        ret = -1;
        goto __exit;
    }

    *value = cb->buffer[cb->head];
    cb->head = (cb->head + 1) % cb->capacity;
    cb->count--;
__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&cb->mutex);
#endif
    return ret;
}




int pika_hal_deque_popTail(pika_hal_deque* cb, void** value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    if (cb->count == 0) {
        ret = -1;  // 队列为空
        goto __exit;
    }

    *value = cb->buffer[cb->tail - 1];
    cb->tail = (cb->tail - 1 + cb->capacity) % cb->capacity;
    cb->count--;
__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&cb->mutex);
#endif
    return ret;
}


int pika_hal_peekHead(pika_hal_deque* cb, void** value) {
    if (cb->count == 0) {
        return -1;
    }

#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    *value = cb->buffer[cb->head];
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&cb->mutex);
#endif

    return 0;
}

int pika_hal_peekTail(pika_hal_deque* cb, void** value) {
    if (cb->count == 0) {
        return -1;  // 队列为空
    }

#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    *value = cb->buffer[(cb->tail - 1 + cb->capacity) % cb->capacity];
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&cb->mutex);
#endif

    return 0;
}


int pika_hal_deque_deinit(pika_hal_deque* cb) {
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    pikaFree(cb->buffer, cb->capacity * sizeof(void*));  // 释放指针数组
    cb->buffer = NULL;
    cb->head = 0;
    cb->tail = 0;
    cb->count = 0;
    cb->capacity = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_destroy(&cb->mutex);
#endif
    pikaFree(cb, sizeof(pika_hal_deque));
    return 0;
}

size_t pika_hal_deque_getCount(pika_hal_deque* cb) {
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&cb->mutex);
#endif
    size_t count = cb->count;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&cb->mutex);
#endif
    return count;
}

int pika_hal_deque_isEmpty(pika_hal_deque* cb) {
    return cb->count == 0;
}

int pika_hal_deque_isFull(pika_hal_deque* cb) {
    return cb->count == cb->capacity;
}

#else

pika_hal_deque* pika_hal_deque_create(size_t capacity) {
    pika_hal_deque* deque = (pika_hal_deque*)pikaMalloc(sizeof(pika_hal_deque));
    if (NULL == deque) {
        return NULL;
    }
    deque->head = NULL;
    deque->tail = NULL;
    deque->count = 0;
    deque->maxlen = capacity;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_init(&deque->mutex);
#endif
    return deque;
}

int pika_hal_deque_deinit(pika_hal_deque* deque) {
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    while (deque->head != NULL) {
        Node* temp = deque->head;
        deque->head = deque->head->next;
        pikaFree(temp, sizeof(Node));
    }
    deque->head = NULL;
    deque->tail = NULL;
    deque->count = 0;
    deque->maxlen = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_destroy(&deque->mutex);
#endif
    pikaFree(deque, sizeof(pika_hal_deque));
    return 0;
}

int pika_hal_deque_appendTail(pika_hal_deque* deque, void* value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    if (deque->count >= deque->maxlen) {
        ret = -1;  // 队列已满
        goto __exit;
    }

    Node* node = (Node*)pikaMalloc(sizeof(Node));
    if (node == NULL) {
        ret = -1;  // 内存分配失败
        goto __exit;
    }
    node->data = value;
    node->prev = deque->tail;
    node->next = NULL;

    if (deque->tail) {
        deque->tail->next = node;
    } else {
        deque->head = node;
    }
    deque->tail = node;
    deque->count++;

__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&deque->mutex);
#endif
    return ret;
}

int pika_hal_deque_appendHead(pika_hal_deque* deque, void* value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    if (deque->count >= deque->maxlen) {
        ret = -1;  // 队列已满
        goto __exit;
    }

    Node* node = (Node*)pikaMalloc(sizeof(Node));
    if (node == NULL) {
        ret = -1;  // 内存分配失败
        goto __exit;
    }
    node->data = value;
    node->prev = NULL;
    node->next = deque->head;

    if (deque->head) {
        deque->head->prev = node;
    } else {
        deque->tail = node;
    }
    deque->head = node;
    deque->count++;

__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&deque->mutex);
#endif
    return ret;
}

int pika_hal_deque_popHead(pika_hal_deque* deque, void** value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    if (deque->count == 0) {
        ret = -1;  // 队列为空
        goto __exit;
    }

    *value = deque->head->data;
    Node* temp = deque->head;
    deque->head = deque->head->next;
    if (deque->head) {
        deque->head->prev = NULL;
    } else {
        deque->tail = NULL;
    }
    deque->count--;
    pikaFree(temp, sizeof(Node));

__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&deque->mutex);
#endif
    return ret;
}

int pika_hal_deque_popTail(pika_hal_deque* deque, void** value) {
    int ret = 0;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    if (deque->count == 0) {
        ret = -1;  // 队列为空
        goto __exit;
    }

    *value = deque->tail->data;
    Node* temp = deque->tail;
    deque->tail = deque->tail->prev;
    if (deque->tail) {
        deque->tail->next = NULL;
    } else {
        deque->head = NULL;
    }
    deque->count--;
    pikaFree(temp, sizeof(Node));

__exit:
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&deque->mutex);
#endif
    return ret;
}

int pika_hal_deque_peekHead(pika_hal_deque* deque, void** value) {
    if (deque->count == 0) {
        return -1;  // 队列为空
    }

#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    *value = deque->head->data;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&deque->mutex);
#endif

    return 0;
}

int pika_hal_deque_peekTail(pika_hal_deque* deque, void** value) {
    if (deque->count == 0) {
        return -1;  // 队列为空
    }

#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    *value = deque->tail->data;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&deque->mutex);
#endif

    return 0;
}

size_t pika_hal_deque_getCount(pika_hal_deque* deque) {
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_lock(&deque->mutex);
#endif
    size_t count = deque->count;
#if PIKA_HAL_CIRCULAR_QUEUE_MUTEX_ENABLE
    pika_platform_thread_mutex_unlock(&deque->mutex);
#endif
    return count;
}

int pika_hal_deque_isEmpty(pika_hal_deque* deque) {
    return deque->count == 0;
}

int pika_hal_deque_isFull(pika_hal_deque* deque) {
    return deque->count == deque->maxlen;
}

#endif
